Convert to an iterative eval loop instead of a recursive one#1409
Open
LadyCailin wants to merge 5 commits intomasterfrom
Open
Convert to an iterative eval loop instead of a recursive one#1409LadyCailin wants to merge 5 commits intomasterfrom
LadyCailin wants to merge 5 commits intomasterfrom
Conversation
This is a major change in the script evaluation process, which changes how "special execution" functions work. Previously, functions could choose to implement execs instead of exec, which received a ParseTree, instead of Mixed. This allowed the individual function to decide how or even if the ParseTree nodes were further executed. This works in general, however it has several drawbacks. In particular, the core evaluation loop loses control over the script once it decends into individual functions. Therefore features like Ctrl+C in command line scripts relied on each of these "flow" functions to implement that feature correctly, and only some of them did. This also prevents new features from being implemented as easily, like a debugger, since the evaluation loop would need to be modified, and every single flow function would need to make the same changes as well. This also has several performance benefits. Using a recursive approach meant that each frame of MethodScript had about 3 Java frames, which is inefficient. The biggest performance change with this is moving away from exception based control flow. Previously, return, break, and continue were all implemented with Java exceptions. This is way more expensive than it needs to be, especially for very unexecptional cases such as return(). Now, when a proc or closure returns, it triggers a different phase in the state machine, instead of throwing an exception. This also unlocks future features that were not possible today. A debugger could have been implemented before (though it would have been difficult) but now an asynchronous debugger can be implemented. async/await is also possible now. Tail call optimizations can be done, execution time quotas, and the profiler can probably be improved.
Previously, callback invocations required re-entering the eval loop from the top, which defeats the purpose of the iterative loop. In principal, the functions that call Callables need to become flow functions to behave correctly, but for basic yield-style invocations, this infrastructure is too heavy, so CallbackYield is a new class which puts the function in terms of an exec-like mechanism, only introducing the Yield object, which is just a queue of operations, effectively. More functions need to convert to this, but as a first start, array_map has been converted. Some of the simpler FlowFunctions might be able to be simplified to this as well.
These are the "easy" functions to convert.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This is a major change in the script evaluation process, which changes
how "special execution" functions work. Previously, functions could
choose to implement execs instead of exec, which received a ParseTree,
instead of Mixed. This allowed the individual function to decide how or
even if the ParseTree nodes were further executed. This works in
general, however it has several drawbacks.
In particular, the core evaluation loop loses control over the script
once it decends into individual functions. Therefore features like
Ctrl+C in command line scripts relied on each of these "flow" functions
to implement that feature correctly, and only some of them did. This
also prevents new features from being implemented as easily, like a debugger,
since the evaluation loop would need to be modified, and every single
flow function would need to make the same changes as well.
This also has several performance benefits. Using a recursive approach
meant that each frame of MethodScript had about 3 Java frames, which is
inefficient. The biggest performance change with this is moving away
from exception based control flow. Previously, return, break, and
continue were all implemented with Java exceptions. This is way more
expensive than it needs to be, especially for very unexecptional cases
such as return(). Now, when a proc or closure returns, it triggers a
different phase in the state machine, instead of throwing an exception.
This also unlocks future features that were not possible today. A
debugger could have been implemented before (though it would have been
difficult) but now an asynchronous debugger can be implemented.
async/await is also possible now. Tail call optimizations can be done,
execution time quotas, and the profiler can probably be improved.